<template>
  <div class="position-relative scene" ref="scene">
    <!-- <div
      class="position-absolute w-100 h-100 bg-dark d-flex justify-content align-items-center"
    >
      <div class="w-50">
        <p class="lead text-light mb-2">加载中</p>
        <div class="progress">
          <div
            class="bg-info text-dark"
            role="progress"
            :style="`width:${progress}%`"
          >
            {{ progress }}%
          </div>
        </div>
      </div>
    </div> -->
  </div>
</template>

<script>
import * as THREE from "three";
// OrbitControls 是对 Threejs 的三维场景进行缩放、平移、旋转操作
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 导入 glb 格式模型，若要导入其他格式模型，可尝试在 loaders 目录下加载其他文件
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import {
  // EffectMaterial,
  RenderPass,
  EffectPass,
  BloomEffect,
  EffectComposer,
} from "postprocessing";

export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: "scene",
  data() {
    return {
      publicPath: process.env.BASE_URL,
      progress: 0,
    };
  },
  methods: {
    init() {
      // scene
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0x000000);

      //Renderer
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(
        this.$refs.scene.clientWidth,
        this.$refs.scene.clientHeight
      );
      this.renderer.toneMapping = THREE.ReinhardToneMapping;
      this.renderer.toneMappingExposure = 3;
      this.renderer.shadowMap.enabled = true;
      this.$refs.scene.appendChild(this.renderer.domElement);

      // Camera
      const aspect =
        this.$refs.scene.clientWidth / this.$refs.scene.clientHeight;
      this.camera = new THREE.PerspectiveCamera(60, aspect, 0.01, 1000);
      this.camera.position.set(0, 3, 5);

      //Camera Consrols
      this.constols = new OrbitControls(this.camera, this.renderer.domElement);
      //   constols.addEventListener("change", this.renderer);
      this.constols.update();

      //Light
      const hemiLight = new THREE.HemisphereLight(0xffeeb1, 0x080820, 2);
      this.scene.add(hemiLight);

      this.spotLight = new THREE.SpotLight(0xffa95c, 4);
      this.spotLight.castShadow = true;
      this.spotLight.shadow.bias = -0.0001;
      this.spotLight.shadow.mapSize.width = 10000;
      this.spotLight.shadow.mapSize.height = 10000;
      this.scene.add(this.spotLight);

      // Post Processing
      this.composer = new EffectComposer(this.renderer);
      this.composer.addPass(new RenderPass(this.scene, this.camera));

      const effectPass = new EffectPass(
        this.camera,
        new BloomEffect({
          intensity: 4,
          luminanceThreshold: 0.7,
          width: 100,
          height: 100,
        })
      );
      this.composer.addPass(effectPass);

      // Loading Manager
      const manager = new THREE.LoadingManager();
      manager.onProgress = (url, itemsLoaded, itemsTotal) => {
        this.progress = (itemsLoaded / itemsTotal) * 100;
        if ((itemsLoaded / itemsTotal) * 100 === 100) {
          setTimeout(() => {
            this.flag = true;
          }, 1000);
        }
      };

      //Loader
      const loader = new GLTFLoader(manager);
      console.log(this.publicPath);
      loader.load(`${this.publicPath}models/gltf/scene.glb`, (reslut) => {
        const model = reslut.scene.children[0];
        model.traverse((n) => {
          if (n.isMEsh) {
            n.castShadow = true;
            n.receiveShadow = true;
            if (n.material.map) n.material.map.anisotropy = 100;
          }
        });
        this.scene.add(model);
        this.animate();
      });
    },
    animate() {
      requestAnimationFrame(this.animate);
      this.spotLight.position.set(
        this.camera.position.x + 5,
        this.camera.position.y + 5,
        this.camera.position.z + 5
      );
      this.composer.render();
    },
    onCanvasResize() {
      this.camera.aspect =
        this.$refs.scene.clientWidth / this.$refs.scene.clientHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(
        this.$refs.scene.clientWidth,
        this.$$refs.scene.clientHeight
      );
      this.composer.setSize(
        this.$refs.scene.clientWidth,
        this.$$refs.scene.clientHeight
      );
    },
  },
  mounted() {
    window.addEventListener("resize", this.onCanvasResize, false);
    this.init();
    console.log(this.$refs.scene.appendChild);
  },
};
</script>

<style scoped>
.scene {
  width: 70%;
  height: 0;
  padding-bottom: 39.375%;
}
.w-20 {
  width: 20%;
}
.h-small {
  height: 10px;
}
@media (max-width: 992px) {
  .scene {
    width: 100%;
    height: 0;
    padding-bottom: 56.25%;
  }
}
</style>
